using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Tomahawk.Runtime.Logic;
using Tomahawk.Runtime.Resources;


namespace Tomahawk.Runtime
{

    /// <summary>
    /// This is the common behaviour for all game states. 
    /// A game state holds it's own ContentManager, 
    /// this way you can free all the assets used by the state
    /// </summary>
    public abstract class GameState
    {
        ContentManager contentManager = null;

        /// <summary>
        /// Get the content manager associated with this state
        /// </summary>
        public ContentManager ContentManager
        {
            get { return contentManager; }
        }

        /// <summary>
        /// Construction logic
        /// </summary>
        public GameState()
        {
            //create the content loader
            contentManager = new ContentManager(Engine.Instance.Services);
        }

        /// <summary>
        /// Define a delegate to pass on notifications between states
        /// </summary>
        public delegate void GameStateNotification(string Result);

        /// <summary>
        /// Handle this event to receive notifications from inside a game state
        /// </summary>
        public event GameStateNotification OnNotification;

        /// <summary>
        /// Notify something to a higher level state
        /// </summary>
        protected void Notify(string Result)
        {
            if (this.OnNotification != null) this.OnNotification(Result);
        }

        /// <summary>
        /// Game state loading stage (assets loading)
        /// </summary>
        public void Load()
        {   
            //if there is a gamestate currently available, unload it first
            GameState prevGameState = Engine.Instance.CurrentGameState;
            if (prevGameState != null)
            {
                Engine.Instance.NotifyBeforeUnload(prevGameState);
                prevGameState.Unload();
                Engine.Instance.ResourceManager.UnloadGlobalPoolIfPendant();
            }

            //initialize the state
            OnInitialize();

            //Set as current
            Engine.Instance.setCurrentGameState(this);

            //let the state load it's assets
            OnLoad();
        }

        /// <summary>
        /// Game state unloading stage (assets unloading)
        /// </summary>
        public void Unload()
        {   
            //Destroy the state
            OnDestroy();

            //Unload the state
            OnUnload();

            //destroy all pendant logic objects
            XWorld.Instance.DestroyAllPendantObjects();

            //clear pendant render commands
            Engine.Instance.MaterialManager.Clear();
            Engine.Instance.ParticlesManager.Clear();
            Engine.Instance.RenderManager.ClearRenderCommandPool();
            Engine.Instance.RenderManager.ClearCommands();

            //Free all the asset loaded by this contentmanager
            this.contentManager.Unload();
            this.contentManager = null;
        }

        #region "Abstract members"

        /// <summary>
        /// Implement this to provide your state loading stage
        /// </summary>
        protected abstract void OnLoad();

        /// <summary>
        /// Implement this to provide you state unloading stage
        /// </summary>
        protected abstract void OnUnload();

        /// <summary>
        /// Implement this to provide start-up logic
        /// </summary>
        protected abstract void OnInitialize();

        /// <summary>
        /// Implement this to provide destruction logic
        /// </summary>
        protected abstract void OnDestroy();

        #endregion

    }

}